package me.zhouzhuo810.magpiex.utils;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.List;

import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresPermission;
import androidx.core.content.FileProvider;

/**
 * Apk安装工具类
 *
 * @author zhouzhuo810
 * @date 6/15/21 1:48 PM
 */
public class ApkUtil {
    
    private ApkUtil() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }
    
    /**
     * 安装 App(支持 8.0)
     * <br>
     * 注意authority的后缀如果不是".fileProvider",请使用{@link ApkUtil#installApkWithAuthority(Context, String, String, String)}方法。
     * <p>8.0 需添加权限
     * {@code <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />}</p>
     *
     * @param context       上下文
     * @param applicationId applicationId
     * @param dirPath       文件夹路径
     * @param fileName      文件名称
     */
    public static void installApk(Context context, String applicationId, String dirPath, String fileName) {
        installApk(context, applicationId, dirPath + File.separator + fileName);
    }
    
    /**
     * 安装 App(支持 8.0)
     * <br>
     * 注意authority的后缀如果不是".fileProvider",请使用{@link ApkUtil#installApkWithAuthority(Context, String, String, String)}方法。
     * <p>8.0 需添加权限
     * {@code <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />}</p>
     *
     * @param context       上下文
     * @param applicationId applicationId
     * @param filePath      文件路径
     */
    public static void installApk(Context context, String applicationId, String filePath) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        if (Build.VERSION.SDK_INT > 23) {
            //FIX ME by ZZ : 7.0
            Uri uri = FileProvider.getUriForFile(context, applicationId + ".fileProvider",
                new File(filePath));
            //这flag很关键
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(new File(filePath)),
                "application/vnd.android.package-archive");
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    
    
    /**
     * 安装 App(支持 8.0)
     * <p>8.0 需添加权限
     * {@code <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />}</p>
     *
     * @param context   上下文
     * @param authority applicationId + .fileProvider
     * @param dirPath   文件夹路径
     * @param fileName  文件名称
     */
    public static void installApkWithAuthority(Context context, String authority, String dirPath, String fileName) {
        installApkWithAuthority(context, authority, dirPath + File.separator + fileName);
    }
    
    /**
     * 安装 App(支持 8.0)
     * <p>8.0 需添加权限
     * {@code <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />}</p>
     *
     * @param context   上下文
     * @param authority applicationId + .fileProvider
     * @param filePath  文件路径
     */
    public static void installApkWithAuthority(Context context, String authority, String filePath) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        if (Build.VERSION.SDK_INT > 23) {
            //FIX ME by ZZ : 7.0
            Uri uri = FileProvider.getUriForFile(context, authority,
                new File(filePath));
            //这flag很关键
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(new File(filePath)),
                "application/vnd.android.package-archive");
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    
    /**
     * 获取当前APP签名，注意需要权限
     * {@code <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />}
     */
    public static byte[] getSignBytes(Context context) {
        PackageManager pm = context.getPackageManager();
        List<PackageInfo> apps = pm
            .getInstalledPackages(PackageManager.GET_SIGNATURES);
        for (PackageInfo info : apps) {
            String packageName = info.packageName;
            //按包名 取签名
            if (packageName.equals(context.getPackageName())) {
                return info.signatures[0].toByteArray();
            }
        }
        return null;
    }
    
    /**
     * 获取当前APP签名的MD5，注意需要权限
     * {@code <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />}
     */
    public static String getSignMd5(Context context) {
        byte[] signBytes = getSignBytes(context);
        return signBytes == null ? null : EncryptUtil.encryptMD5ToString(signBytes);
    }
    
    /**
     * 获取公钥，注意需要权限
     * {@code <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />}
     */
    public static String getPublicKey(Context context) {
        byte[] signature = getSignBytes(context);
        try {
            CertificateFactory certFactory = CertificateFactory
                .getInstance("X.509");
            X509Certificate cert = (X509Certificate) certFactory
                .generateCertificate(new ByteArrayInputStream(signature));
            return cert.getPublicKey().toString();
        } catch (CertificateException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 获取签名SHA1
     */
    public String getSHA1(Context context) throws Exception {
        String sha1 = "";
        if (context == null) {
            return "";
        }
        PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
        byte[] cert = info.signatures[0].toByteArray();
        MessageDigest digest = MessageDigest.getInstance("SHA1");
        byte[] publicKey = digest.digest(cert);
        StringBuilder hexString = new StringBuilder();
        for (byte b : publicKey) {
            String appendString = Integer.toHexString
                ((b & 0xFF) | 0x100).substring(1, 3).toUpperCase();
            hexString.append(appendString);
            hexString.append(":");
        }
        if (hexString.length() > 1) {
            sha1 = hexString.substring(0, hexString.length() - 1);
        }
        return sha1;
    }
}
